home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
VideoToolbox 96.06.15
/
VideoToolboxSources
/
SndPlay1.c
< prev
next >
Wrap
Text File
|
1996-06-06
|
5KB
|
134 lines
/*
SndPlay1.c
SndPlay1(snd) plays a sound, asynchronously, i.e. it returns immediately, while the
sound is still playing. The argument is a handle to a snd resource. If a sound is
still playing from a previous call to SndPlay1, it is allowed to finish before
SndPlay1 closes and reopens the channel and begins the new sound.
SndPlay1(NULL) waits for any previously SndPlay1-initiated sound to end and then closes the channel.
SndStop1() closes the channel immediately.
SndDone1() returns true if the last sound initiated by SndPlay1() has finished.
Apple advises against leaving the channel open for extended periods, because the open
channel blocks SysBeep. To minimize this, make sure to call SndPlay1(NULL) or SndStop1()
to close the channel when you no longer need it.
The easiest way to get a sound that you can play is to call GetNamedResource().
Here's a complete program to get a sound and play it.
Handle snd;
snd=GetNamedResource('snd ',"\pSimple Beep");
SndPlay1(snd); // start snd playing, and return immediately, while it's playing
// do something useful here
SndPlay1(NULL); // wait till snd is done, then close and dispose of sound channel
ReleaseResource(snd);
It's also easy to create your own snd in memory, as a series of commands,
following the instructions in Inside Mac:Sound. Use VideoToolbox CreateTrialsSnds.c as an example.
As of 1994, the Apple Sound Manager has the annoying characteristic of insisting on loading
any synth that's mentioned in a snd resource, even if that synth is already loaded,
which causes an error. This makes it necessary to dispose of and recreate the
snd channel before each new sound, which these routines do.
NOTE: The snd is not locked while being played. I don't know whether that's necessary.
It seems to work ok as is, on both 68k and ppc machines, but I haven't stressed it. In
particular, I don't move memory while the sound is playing. I probably ought to lock it
down and HoldMemory on the snd while it's playing. However, that would complicate the
program slightly, since the locking and unlocking would have to happen in different
routines, below, and the address of the snd would have to be communicated between them,
presumably by a variable global to this file.
HISTORY:
3/30/92 dgp wrote it.
4/1/92 dgp renamed it and commented out the printf's.
7/9/93 dgp Test MATLAB in if() instead of #if.
5/28/94 dgp Made compatible with Apple's Universal Headers. Thanks to Bob Dougherty
(wolfgang@cats.ucsc.edu) for reporting the incompatibility.
9/5/94 dgp removed assumption in printf's that int==short.
9/10/94 dgp cosmetic
10/5/94 dgp simplified SndCallBack1 until it stopped crashing when I run native on ppc.
10/27/94 dgp It is very annoying for the machine to crash anytime you try to quit your
application by escaping via MacsBugs escape to shell. The problem is that CodeWarrior
doesn't attach the atexit() tasks to _EscapeToShell. So I do it here.
7/1/95 dgp just call AtExitToShell(), without any conditionals. Special cases, e.g. MATLAB,
are handled in AtExitToShell.c.
*/
#include "VideoToolbox.h"
//#include <Sound.h>
static pascal void SndCallBack1(SndChannelPtr channelPtr,SndCommand command);
static SndChannel *channelPtr=NULL,channel;
static SndCommand callBack;
#if !UNIVERSAL_HEADERS
#define NewSndCallBackProc (SndCallBackUPP)
typedef ProcPtr SndCallBackUPP;
#endif
#if UNIVERSAL_HEADERS<2
#define SndListHandle Handle
#endif
OSErr SndPlay1(Handle snd)
{
int error=0;
static Boolean firstTime=1;
static SndCallBackUPP sndCallBackProc;
if(snd!=NULL)HNoPurge(snd); // make sure snd is not purged while we're allocating memory
if(firstTime){
sndCallBackProc=NewSndCallBackProc(SndCallBack1);
AtExitToShell(SndStop1);
firstTime=0;
}
if(channelPtr!=NULL)error=SndDisposeChannel(channelPtr,FALSE); // wait till done
channelPtr=NULL;
if(error)return error;
if(snd==NULL)return 0;
if(1)error=SndNewChannel(&channelPtr,0,0L,sndCallBackProc); // allocates space for 128 snds.
else{
channelPtr=&channel;
channelPtr->qLength=10; // how many snd commands to allow space for. CreateTrialSnds.c snds use 4.
error=SndNewChannel(&channelPtr,0,0L,sndCallBackProc);
if(error)channelPtr=NULL;
}
if(error){
printf("%s %d:SndNewChannel failed with error %d\007\n",__FILE__,__LINE__,error);
return error;
}
error=SndPlay(channelPtr,(SndListHandle)snd,TRUE);
if(error){
printf("%s %d:SndPlay failed with error %d\007\n",__FILE__,__LINE__,error);
return error;
}
callBack.cmd=callBackCmd;
callBack.param1=0;
error=SndDoCommand(channelPtr,&callBack,FALSE);
if(error)printf("%s %d:SndDoCommand failed with error %d\007\n",__FILE__,__LINE__,error);
return error;
}
void SndStop1(void)
{
if(channelPtr!=NULL)SndDisposeChannel(channelPtr,TRUE); // immediately
channelPtr=NULL;
}
short SndDone1(void)
// Returns 1 if the last sound initiated by SndPlay1 has finished. Otherwise 0.
{
return callBack.param1;
}
#if (THINK_C || THINK_CPLUS || SYMANTEC_C)
#pragma options(!profile) // Disable profiling because A5 may be invalid.
#endif
#if __MWERKS__ && __profile__
#pragma profile off // on 68k it would be dangerous to call the profiler from here
#endif
static pascal void SndCallBack1(SndChannelPtr channelPtr,SndCommand command)
// Load a short int.
// Called back by sound manager. Lets us know when sound is done.
{
channelPtr; // prevent "unused argument" warning
command.param1=1;
}